/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package pt.mleiria.cipher;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import org.apache.commons.codec.binary.Base64;
import pt.mleiria.algorithm.Transformation;
import pt.mleiria.utils.IOUtils;

/**
 *
 * @author NB13712
 */
public class Crypto {

    private final String transformation;
    private final Key key;
    
    /**
     * 
     * @param transformation
     * @param key 
     */
    public Crypto(final Transformation transformation, final Key key) {
        this.transformation = transformation.value();
        this.key = key;
    }
    /**
     * 
     * @param transformation
     * @param keyFile
     * @throws IOException
     * @throws FileNotFoundException
     * @throws ClassNotFoundException 
     */
    public Crypto(final Transformation transformation, final String keyFile) throws IOException, FileNotFoundException, ClassNotFoundException {
        this.transformation = transformation.value();
        this.key = IOUtils.deSerializeKey(keyFile);
    }
    
    /**
     * 
     * @param plainText
     * @return cipherText
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException 
     */
    public String encrypt(final String plainText) throws NoSuchAlgorithmException, NoSuchPaddingException, 
            InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
        
        final Cipher cipher = Cipher.getInstance(transformation);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        final byte[] stringBytes = plainText.getBytes("UTF-8");
        final byte[] raw = cipher.doFinal(stringBytes);
        final String cipherText = Base64.encodeBase64String(raw);
        return cipherText;
    }
    /**
     * 
     * @param cipherText
     * @return plaintext
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException 
     */
    public String decrypt(final String cipherText) throws NoSuchAlgorithmException, NoSuchPaddingException, 
            InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
        
        final Cipher cipher = Cipher.getInstance(transformation);
        cipher.init(Cipher.DECRYPT_MODE, key);
        final byte[] raw = Base64.decodeBase64(cipherText);
        final byte[] stringBytes = cipher.doFinal(raw);
        final String plainText = new String(stringBytes, "UTF-8");
        return plainText;
    }
    /**
     * 
     * @param keyFile
     * @param plainText
     * @return cipherText
     * @throws IOException
     * @throws FileNotFoundException
     * @throws ClassNotFoundException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchPaddingException
     * @throws InvalidKeyException
     * @throws UnsupportedEncodingException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException 
     */
    public String encrypt(final String keyFile, final String plainText) throws IOException, FileNotFoundException, ClassNotFoundException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException{
        IOUtils.serializeKey(key, keyFile);
        return encrypt(plainText);
    }
    
}
